home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 02 Useful Techniques / 08 Zarozinski / src / ffllapi / FuzzyOutVariable.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-28  |  9.0 KB  |  413 lines

  1.  
  2. //
  3. // File:    FuzzyOutVariable.cpp
  4. //
  5. // Purpose:    This file contains  code for the FuzzyOutVariable class
  6. //
  7. // Copyright ⌐ 1999-2001 Louder Than A Bomb! Software
  8. //
  9. // This file is part of the FFLL (Free Fuzzy Logic Library) project (http://ffll.sourceforge.net)
  10. // It is released under the BSD license, see http://ffll.sourceforge.net/license.txt for the full text.
  11. //
  12.   
  13. #include "FuzzyModelBase.h"
  14. #include "FuzzySetBase.h"
  15. #include "FuzzyOutVariable.h"
  16. #include "COGDefuzzVarObj.h"
  17. #include "MOMDefuzzVarObj.h"
  18. #include "FuzzyOutSet.h"
  19.  
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. //
  27. // Function: FuzzyOutVariable()
  28. // 
  29. // Purpose:    default constructor 
  30. // 
  31. // Arguments:
  32. //
  33. //        FuzzyModelBase* _parent - model that this variable is part of
  34. // 
  35. // Returns:
  36. //
  37. //        nothing
  38. // 
  39. // Author:    Michael Zarozinski    
  40. // Date:    08/05/01
  41. // 
  42. // Modification History
  43. // Author        Date        Modification
  44. // ------        ----        ------------
  45. //
  46. //
  47.  
  48. FuzzyOutVariable::FuzzyOutVariable(FuzzyModelBase* _parent) : FuzzyVariableBase(_parent), FFLLBase(_parent) 
  49. {
  50.     defuzz_obj = NULL;
  51.  
  52.     // default to MAX composition
  53.     composition_method =  COMPOSITION_OPERATION::MAX;
  54.  
  55.     // default to Center of Gravity defuzzification
  56.     set_defuzz_method( DefuzzVarObj::DEFUZZ_TYPE::COG);
  57.  
  58. }; // end FuzzyOutVariable::FuzzyOutVariable()
  59.  
  60. //
  61. // Function: ~FuzzyOutVariable()
  62. // 
  63. // Purpose:    default destructor 
  64. // 
  65. // Arguments:
  66. //
  67. //        none
  68. // 
  69. // Returns:
  70. //
  71. //        nothing
  72. // 
  73. // Author:    Michael Zarozinski    
  74. // Date:    08/05/01
  75. // 
  76. // Modification History
  77. // Author        Date        Modification
  78. // ------        ----        ------------
  79. //
  80. //
  81. FuzzyOutVariable::~FuzzyOutVariable()
  82. {
  83.     if (defuzz_obj)
  84.         delete defuzz_obj;
  85.  
  86. }; // FuzzyOutVariable::~FuzzyOutVariable()
  87.  
  88.  
  89. //
  90. // Function:    set_defuzz_method()
  91. // 
  92. // Purpose:        Set the defuzzification method for the output variable (and sets)
  93. // 
  94. // Arguments:
  95. //
  96. //        int type - type of defuzzification. This should be one of the 
  97. //        DefuzzVarObj::DEFUZZ_TYPE enum values
  98. // 
  99. // Returns:
  100. //
  101. //        0 - success
  102. //        non-zero - failure
  103. // 
  104. // Author:    Michael Zarozinski    
  105. // Date:    08/01
  106. // 
  107. // Modification History
  108. // Author        Date        Modification
  109. // ------        ----        ------------
  110. //
  111. //
  112. int FuzzyOutVariable::set_defuzz_method(int type)
  113. {
  114.  
  115.     // if we have a defuzz object, delete it cuz we're gonna
  116.     // create one below based on the defuzz method passed in
  117.     if (defuzz_obj)
  118.         {
  119.         // if we already have this type of defuzz, nothing to do...
  120.         if (defuzz_obj->get_defuzz_type() == type)
  121.             return 0; // nothing to do
  122.  
  123.         // delete the old one...
  124.         delete defuzz_obj;
  125.         defuzz_obj = NULL;
  126.  
  127.         } // end if we have an existing defuzz object
  128.  
  129.     switch(type)
  130.         {
  131.         case DefuzzVarObj::DEFUZZ_TYPE::COG:
  132.             
  133.             defuzz_obj = new COGDefuzzVarObj(this);
  134.             break;
  135.  
  136.         case DefuzzVarObj::DEFUZZ_TYPE::MOM:
  137.  
  138.             defuzz_obj = new MOMDefuzzVarObj(this);
  139.             break;
  140.  
  141.         default:
  142.             set_msg_text(ERR_INVALID_DEFUZZ_MTHD);
  143.             return -1;
  144.  
  145.         } // end switch on type
  146.  
  147.     if (!defuzz_obj)
  148.         {
  149.         // problem allocating memory
  150.         // NOTE: in MSVC new returns NULL if there's not enough memory. If this is ported
  151.         // to a diff platform new may throw a std::bad_alloc exception it it can't alloc the memory.
  152.          set_msg_text(ERR_ALLOC_MEM);
  153.         assert(defuzz_obj != NULL);
  154.         return -1;
  155.         } // end if error allocating memory
  156.  
  157.      FuzzyOutSet*    set;    // output set
  158.  
  159.     // loop through all the sets and change the defuzz method 
  160.     for (int i = 0; i < get_num_of_sets(); i++)
  161.         {
  162.         set = get_set(i);
  163.  
  164.         set->set_defuzz_method(type);
  165.  
  166.         } // end loop through sets
  167.  
  168.     return 0;
  169.  
  170. } // end FuzzyOutVariable::set_defuzz_method()
  171.  
  172.  
  173. //
  174. // Function:    set_composition_method()
  175. // 
  176. // Purpose:        Set the composition method for the output variable
  177. // 
  178. // Arguments:
  179. //
  180. //        int method - method of composition. This should be one of the 
  181. //        FuzzyOutVariable::COMPOSITION_OPERATION enum values
  182. // 
  183. // Returns:
  184. //
  185. //        0 - success
  186. //        non-zero - failure
  187. // 
  188. // Author:    Michael Zarozinski    
  189. // Date:    08/01
  190. // 
  191. // Modification History
  192. // Author        Date        Modification
  193. // ------        ----        ------------
  194. //
  195. //
  196.  
  197. int FuzzyOutVariable::set_composition_method(int method)    
  198. {
  199.     // validate
  200.  
  201.     switch (method)
  202.         {
  203.         case COMPOSITION_OPERATION::MIN:
  204.         case COMPOSITION_OPERATION::MAX:
  205.             composition_method = method;
  206.             break;
  207.  
  208.         default:
  209.             // invalid method  
  210.             set_msg_text(ERR_INVALID_COMP_MTHD);
  211.             return -1;    
  212.  
  213.         } // end switch on method
  214.     
  215.     return 0;
  216.  
  217. } // end FuzzyOutVariable::set_composition_method
  218.  
  219. //
  220. // Function:    calc_output_value()
  221. // 
  222. // Purpose:        Calculate the defuzzified value for this output variable
  223. //
  224. // Arguments:
  225. //
  226. //        DOMType* out_set_dom_arr - array of DOM values for each set in the output variable
  227. //
  228. // Returns:
  229. //
  230. //        RealType - the defuzzifed value. FLT_MIN is returned if no output sets are active
  231. //
  232. // Author:    Michael Zarozinski
  233. // Date:    7/00
  234. // 
  235. // Modification History
  236. // Author    Date        Modification
  237. // ------    ----        ------------
  238. //
  239. //
  240. RealType FuzzyOutVariable::calc_output_value(DOMType* out_set_dom_arr ) const
  241. {
  242.      assert(defuzz_obj);
  243.  
  244.     RealType out_value = defuzz_obj->calc_value(out_set_dom_arr);
  245.  
  246.     // Note:  if we don't have an output value FLT_MIN is returned from above func call
  247.     return out_value;
  248.  
  249. }; // end FuzzyOutVariable::calc_output_value()
  250.  
  251.  
  252.  
  253. //
  254. // Function: init()
  255. // 
  256. // Purpose:    Initialize variable identifier and make it unique if applicable
  257. // 
  258. // Arguments:
  259. //
  260. //        const wchar_t*    _id                    -    identifier for the variable
  261. //        bool            create_unique_id    -    if true, alter the identifier (if needed) to make it unique) default = true
  262. //
  263. // Returns:
  264. //
  265. //        0 - success
  266. //        non-zero - failure
  267. // 
  268. // Author:    Michael Zarozinski    
  269. // Date:    1/99
  270. // 
  271. // Modification History
  272. // Author        Date        Modification
  273. // ------        ----        ------------
  274. //
  275. //
  276.         
  277. int FuzzyOutVariable::init(const wchar_t* _id, bool create_unique_id /* = true */)
  278. {
  279.     int name_len;    // length of the name
  280.  
  281.     if (_id == NULL)
  282.         name_len = 30;
  283.     else
  284.         name_len = wcslen(_id) + 5;
  285.  
  286.     wchar_t* tmp_name = new wchar_t[name_len]; // temp var to hold var name
  287.  
  288.     // if no name is passed in name it "Output"
  289.      if (_id == NULL)
  290.         swprintf(tmp_name, L"%s", load_string(STR_OUTPUT));  
  291.      else
  292.         swprintf(tmp_name, L"%s", _id );  
  293.      
  294.      // set the name.  NOTE: this set_id() performs a check to ensure that the variable name is UNIQUE
  295.     // for this model.  
  296.  
  297.     int ret_value; // return value
  298.  
  299.     if (!create_unique_id)
  300.         {
  301.         ret_value = set_id(tmp_name);
  302.         }
  303.     else
  304.         {
  305.         ret_value = 0;
  306.  
  307.          int counter = 0; // value to add to identifier to make it unique
  308.  
  309.         while (set_id(tmp_name))
  310.             {
  311.             // rename variable...
  312.             if (_id == NULL)
  313.                 swprintf(tmp_name, L"%s %d", load_string(STR_OUTPUT), counter  );  
  314.              else
  315.                 swprintf(tmp_name, L"%s %d", _id, counter );  
  316.  
  317.             counter++;
  318.  
  319.             // clear message text (should say "var not unique" right now)
  320.             set_msg_text(NULL);
  321.             
  322.             } // end while !unique id
  323.  
  324.         }// end if rename var if not unique
  325.  
  326.     // free memory
  327.     delete[] tmp_name;
  328.  
  329.     return ret_value;
  330.  
  331. } // end FuzzyOutVariable::init()
  332.  
  333.  
  334. //
  335. // Function: convert_idx_to_value()
  336. // 
  337. // Purpose:    This function converts an index (into the values[] array) to 
  338. //            an 'x' value between left_x and right_x for this variable
  339. //            NOTE: this is the OUTPUT var version. -1 is a valid "current_x_value"
  340. //            value for it (if no output sets are active) so we handle it special.
  341. // 
  342. // Arguments:
  343. //
  344. //        int idx -    index to convert to a value
  345. //
  346. // Returns:
  347. //
  348. //        RealType - x value for the index passed in
  349. // 
  350. // Author:    Michael Zarozinski    
  351. // Date:    11/28/01
  352. // 
  353. // Modification History
  354. // Author        Date        Modification
  355. // ------        ----        ------------
  356. //
  357. //
  358.  
  359. RealType FuzzyOutVariable::convert_idx_to_value(int idx) const
  360. {
  361.     assert(idx >= -1);
  362.  
  363.     if (idx == -1)
  364.          return FLT_MIN;
  365.      else
  366.         return FuzzyVariableBase::convert_idx_to_value(idx);
  367.  
  368. };
  369.  
  370. /////////////////////////////////////////////////////////////////////
  371. ////////// Trivial Functions That Don't Require Headers /////////////
  372. /////////////////////////////////////////////////////////////////////
  373.  
  374. FuzzyOutSet* FuzzyOutVariable::get_set(int idx) const
  375. {
  376.     return dynamic_cast<FuzzyOutSet*>(FuzzyVariableBase::get_set(idx));
  377. }  
  378.  
  379. int FuzzyOutVariable::get_defuzz_method()
  380. {
  381.     if (defuzz_obj)
  382.         return defuzz_obj->get_defuzz_type();
  383.     else
  384.         return -1;
  385. }
  386.     
  387. bool FuzzyOutVariable::is_output() const 
  388. {
  389.     return true;
  390. }; 
  391. int FuzzyOutVariable::get_composition_method()
  392.     return composition_method;
  393. }
  394. FuzzySetBase* FuzzyOutVariable::new_set()
  395. {
  396.     return new FuzzyOutSet(this);
  397. };
  398. const char* FuzzyOutVariable::get_fcl_block_start()    
  399.     return "VAR_OUTPUT"; 
  400. };        
  401. const char* FuzzyOutVariable::get_fcl_block_end() 
  402.     return "END_VAR"; 
  403. };
  404.  
  405. int FuzzyOutVariable::init(const wchar_t* _id, RealType _left_x, RealType _right_x, bool create_unique_id /* = true */)
  406. {
  407.     // call ancestore
  408.     return FuzzyVariableBase::init(_id, _left_x, _right_x, create_unique_id);
  409. };
  410.